Hex Workshop
16-bit v2.10
16-bit Cracking in WinNT
by
ytc_ [tNO '99]
Target | Hex Workshop 16-bit v2.10 |
URL | Not available (but target can be found in ORCPAK2.ZIP at +Greythorne's website) |
Tools used | Softice v3.x for WinNT |
Win32 API Help (Optional) | |
Protection | Serial Only |
Level | Beginners/Newbies |
Introduction
|
It is a well known fact that when cracking in WinNT, there are a few limitations we have to cope with when cracking serial protections :-
Normally, in Win9x, one could use the 16-bit APIs when cracking 16-bit applications, such as GetDlgItemText, GetWindowText and even hmemcpy. Some might also prefer the 'task', 'hwnd [module-name]', 'bmsg [hwnd] wm_gettext' method to get to the protection scheme. Others would enter a bogus serial and do a 's 0 L FFFFFFFF "bogus_serial_here"'. The rest are hard-core 'hmemcpy', 'bpr' users which works about 99.9% in all applications. But, in WinNT, things are different with the limitations described above. What can we do? First, we need to know that when 16-bit programs are executed in WinNT, it is being thunked upwards first, then the normal 32-bit API calls are used. In Win9x, the process are the reverse, ie. 32-bit programs are thunked downwards first to 16-bit level. With this knowledge, we know that using the normal 32-bit APIs will also work when cracking 16-bit applications.
Essay
|
I will assume that you have already set up your copy of Softice and know how to use it well, including knowing what the shortcut function keys are (F8, F10, F11 and F12). If not, I suggest you read some other essays on how to set up Softice first before continuing. I will also assume that you have a fair knowledge of assembly language.
Like any other programs, run hworks16.exe and go to the about screen where the registration box is located. Notice that this is a serial only type of protection scheme. Enter some bogus numbers into the edit-box (I use my favourite '1123583145'), Ctrl-D into Softice and place breakpoints on GetDlgItemTextA and GetWindowTextA. Ctrl-D back to program (or F5) and click on the 'Register' button. Immediately, you find yourself at the beginning of the GetWindowTextA procedure. Press F11 once to get back to the caller and looking at the bottom bar of your code window, you immediately know that you are in the wow32.dll process.
Looking at EAX, you notice that the value returned is 9. Checking back with your Win32 API help guide, you should know that this not the break we are looking for because GetWindowTextA should return the length of my bogus serial, which is 0Ah (10d) in EAX. So, ignore this break and Ctrl-D or F5 again, followed by F11 until you see 0Ah in EAX (which is on the 5th break). At one point, you might need to move your mouse a little to continue. Press F12 a few times until you find yourself in HWORKS(03). Please take note the the addresses might be different from what you see on your screen.
15FF:254E 9AB3343703 CALL 0337:34B3 15FF:2553 EB10 JMP 2565 <= you land here 15FF:2555 50 PUSH AX 15FF:2556 C45E06 LES BX,[BP+06] 15FF:2559 26FF7702 PUSH WORD PTR ES:[BX+02] 15FF:255D 26FF37 PUSH WORD PTR ES:[BX] 15FF:2560 9AD4144710 CALL 1047:14D4 15FF:2565 5E POP SI 15FF:2566 C9 LEAVE 15FF:2567 CA0800 RETF 0008
At this point, you notice that there is a RETF instruction just a few lines below. Immediately you know that you are not nearing the protection scheme yet. You press F12 a few more times and stop when you encounter the first conditional jump.
166F:15AD 9A3826BF16 CALL 16BF:2638 166F:15B2 8E4608 MOV ES,[BP+08] <== you land here 166F:15B5 26FF743A PUSH WORD PTR ES:[SI+3A] ; segment to bogus serial 166F:15B9 26FF7438 PUSH WORD PTR ES:[SI+38] ; offset to bogus serial 166F:15BD 8D46EC LEA AX,[BP-14] 166F:15C0 16 PUSH SS ; segment 2 166F:15C1 50 PUSH AX ; offset 2 166F:15C2 9A3E75AF15 CALL 15AF:753E ; copies bogus serial to SS:AX 166F:15C7 83C408 ADD SP,08 166F:15CA 8D46EC LEA AX,[BP-14] 166F:15CD 16 PUSH SS 166F:15CE 50 PUSH AX ; SS:AX points to bogus serial 166F:15CF 9A381FAF15 CALL 15AF:1F38 <= !!! 166F:15D4 83C404 ADD SP,04 166F:15D7 0BC0 OR AX,AX <= !!! 166F:15D9 7552 JNZ 162D <= !!!!!!!!!! 166F:15DB 6A75 PUSH 75 166F:15DD 6A01 PUSH 01 166F:15DF 50 PUSH AX 166F:15E0 50 PUSH AX 166F:15E1 50 PUSH AX 166F:15E2 8D46C0 LEA AX,[BP-40] 166F:15E5 16 PUSH SS 166F:15E6 50 PUSH AX 166F:15E7 9A2E126F16 CALL 166F:122E 166F:15EC 8D46C0 LEA AX,[BP-40] 166F:15EF 16 PUSH SS 166F:15F0 50 PUSH AX 166F:15F1 9A4431BF16 CALL 16BF:3144
With enough experience, one can guess immediately that the unconditional jump at 166F:15D9 is the 'deciding' jump between 'bad_cracker' and 'good_cracker'. And, the call above it must be the location of the serial generating routine. Now, a lazy cracker might stop here and change the 'jnz 162D' to a 'jz 162D', recieve the 'congratulations, you cracked my program' message, risking the possibility that there might be another check somewhere. I choose the better, but slightly harder way... find a valid serial!
By now, you should have cleared all breakpoints (bc *) and placed a fresh new one on 166F:15CF. Trace into this call (F8) and you look around for clues.
15AF:1F38 C8140000 ENTER 0014,00 ; beginning of routine ... 15AF:1F3E C47E06 LES DI,[BP+06] ; loads offset of bogus serial 15AF:1F41 B9FFFF MOV CX,FFFF 15AF:1F44 33C0 XOR AX,AX 15AF:1F46 F2AE REPNZ SCASB ; standard scheme to retrieve length of string 15AF:1F48 F7D1 NOT CX 15AF:1F4A 49 DEC CX ; CX now contains length of bogus serial 15AF:1F4B 83F908 CMP CX,08 ; compares serial length with 8 15AF:1F4E 7575 JNZ 1FC5 ; jump to end of routine!! ... 15AF:1F6B 52 PUSH DX 15AF:1F6C 50 PUSH AX 15AF:1F6D 0E PUSH CS 15AF:1F6E E8F3FE CALL 1E64 ; interesting call!! ... 15AF:1FA2 B90200 MOV CX,0002 15AF:1FA5 8BF8 MOV DI,AX 15AF:1FA7 8D76FC LEA SI,[BP-04] 15AF:1FAA 8EC2 MOV ES,DX 15AF:1FAC D1E9 SHR CX,1 15AF:1FAE 1BC0 SBB AX,AX 15AF:1FB0 3BC9 CMP CX,CX 15AF:1FB2 F3A7 REPZ CMPSW ; compare!! 15AF:1FB4 7504 JNZ 1FBA 15AF:1FB6 2BC8 SUB CX,AX 15AF:1FB8 F3A6 REPZ CMPSB 15AF:1FBA 7406 JZ 1FC2 15AF:1FBC 33C0 XOR AX,AX ; clear AX flag!! 15AF:1FBE 5E POP SI 15AF:1FBF 5F POP DI 15AF:1FC0 C9 LEAVE 15AF:1FC1 CB RETF 15AF:1FC2 B80100 MOV AX,0001 ; set AX flag!! 15AF:1FC5 5E POP SI 15AF:1FC6 5F POP DI 15AF:1FC7 C9 LEAVE 15AF:1FC8 CB RETF
A-hah! Right at the heart of the scheme! First, it checks if your serial is 8 digits long, and 'jump bad_cracker' if it isn't. Then the line I marked as 'interesting call' calculates a 2-character string based on the 3-8th characters of the bogus serial. Then compares it with the FIRST 2 DIGITS OF BOGUS SERIAL and jump if it not equal. You now clear all your breakpoints and place another fresh new one right on the compare instruction, then restart the registration process, this time using a 8-digit bogus serial (I truncated mine to 11235831). You break right on the compare instruction. Do a 'd es:di' and you see your bogus serial. Do a 'd ds:si' and you see the magic characters (in my case, it is HX). Restart the program again, this time with the CORRECT SERIAL. Before clicking on 'Register', you disable all your breakpoints (bd *). DO NOT CLEAR THEM YET, JUST IN CASE. Now you click on 'Register' and BINGO!! You see the 'Thank you for cracking my program successfully' message, enter your name and organization, and enjoy the program as long as you like!
Final Notes
|
The reason I choose an old version of Hex Workshop is because we need to first study old protection schemes in order to grasp a main idea of the art of cracking because older protection schemes are normally easier than the newer and modern ones. Who knows, maybe this tutorial might shed some light on some of you who are still struggling with the latest version of Hex Workshop.
Finally, after cracking this program, keep the serial number to yourself and remove the program. If you want the program, buy it and support the authors who deserves it for all the work they have done.
Greets
|
There's a lot of people that I know, so I'll just greet everyone, especially those in #tno, #win32asm, #cracking4newbies and #cracking at EFNet.
Email :
y_t_c@usa.net
Website : http://ytc98.cjb.net